package engine.hw;

import engine.config.Config;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Mouse;

public class Pointer 
{
    
    //<editor-fold defaultstate="collapsed" desc="Singleton">
    private static Pointer singleton;
    
    public static Pointer get()
    {
        if (singleton == null)
        {
            singleton = new Pointer();
        }
        return singleton;
    }
    //</editor-fold>
    
    
    public static final int CLICK_L = 0;
    public static final int CLICK_R = 1;
    public static final int CLICK_MID = 2;
    
    
    private int mouseX;
    private int mouseY;
    //<editor-fold defaultstate="collapsed" desc="getMouse[X/Y]">
    public int getMouseX()
    {
        return this.mouseX;
    }
    
    public int getMouseY()
    {
        return this.mouseY;
    }
    //</editor-fold>
    
    private int mouseDX;
    private int mouseDY;
    //<editor-fold defaultstate="collapsed" desc="getMouse[DX/DY]">
    public int getMouseDX()
    {
        return this.mouseDX;
    }
    
    public int getMouseDY()
    {
        return this.mouseDY;
    }
    //</editor-fold>
    
    private float mouseSensX;
    private float mouseSensY;
    //<editor-fold defaultstate="collapsed" desc="getSensitivity[X/Y]">
    public float getSensitivityX()
    {
        return this.mouseSensX;
    }
    
    public float getSensitivityY()
    {
        return this.mouseSensY;
    }
    //</editor-fold>
    
    private boolean[] mouseState;
    private boolean[] mousePrev;
    
    private boolean mouseWheelUp;
    private boolean mouseWheelDown;
    //<editor-fold defaultstate="collapsed" desc="isMouseWheel[Up/Down]">
    public boolean isMouseWheelUp()
    {
        return this.mouseWheelUp;
    }
    
    public boolean isMouseWheelDown()
    {
        return this.mouseWheelDown;
    }
    //</editor-fold>
    
    private boolean mouseGrabbed;
    //<editor-fold defaultstate="collapsed" desc="setGrabbed">
    public void setGrabbed(boolean grabbed)
    {
        if (grabbed != this.mouseGrabbed)
        {
            Mouse.setGrabbed(grabbed);
            this.mouseGrabbed = grabbed;
        }
    }
    //</editor-fold>
    
    public void setPos(int xpos, int ypos) 
    {
        Mouse.setCursorPosition(xpos, ypos);
    }
    
    private Pointer() 
    {
    }
    
    public void initialize(Config cfgFile)
    {
        this.mouseState = new boolean[3];
        this.mousePrev = new boolean[3];
        try 
        {
            Mouse.create();
        }
        catch (LWJGLException e)
        {
            System.out.println(e);
            System.exit(1);
        }
        this.mouseSensX = cfgFile.getFloat("MouseSensitivityHorizontal");
        this.mouseSensY = cfgFile.getFloat("MouseSensitivityVertical");
        this.setGrabbed(cfgFile.getBool("MouseGrabbedAtStart"));
    }
    
    public void update() 
    {
        this.mouseDX = Mouse.getDX(); // Update mouse input vars
        this.mouseDY = Mouse.getDY();
        this.mouseX = Mouse.getX();
        this.mouseY = Mouse.getY();
        for (int i = 0; i < 3; i++) 
        {
            boolean isDown = Mouse.isButtonDown(i);
            this.mousePrev[i] = this.mouseState[i];
            this.mouseState[i] = isDown;
        }
        int dwheel = Mouse.getDWheel();
        this.mouseWheelUp = dwheel > 0;
        this.mouseWheelDown = dwheel < 0;
    }
    
    public boolean isDown(int button) 
    {
        return this.mouseState[button];
    }

    public boolean wasPressed(int button) 
    {
        return (
            this.mouseState[button] && 
            !this.mousePrev[button]
        );
    }

    public boolean wasReleased(int button) 
    {
        return (
            !this.mouseState[button] && 
            this.mousePrev[button]
        );
    }

    public void destroy() 
    {
        this.mouseState = null;
        this.mousePrev = null;
        Mouse.destroy();
    }
    
}
